﻿using CCManger.Common.Message;
using DotNetty.Handlers.Timeout;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Groups;
using Serilog;
using System;
using System.Collections.Concurrent;
using System.Net;
using System.Threading.Tasks;

namespace CCManger.Server
{
    public class HelloServerHandler : ChannelHandlerAdapter //管道处理基类，较常用
    {
        public event CommandReceiveEvent MessageReceived;

        public event MessageSendEvent MessageSend;

        public event MessageGroupSendEvent MessageGroupSend;

        public IChannelHandlerContext _Socket = null;

        public async void SendData<T>(T obj)
        {
            try
            {
                await _Socket.WriteAndFlushAsync(obj);
            }
            catch (Exception ex) { }
        }

        public void GroupSendData<T>(T obj)
        {
            try
            {
                // AllClients.Values.ToList().ForEach(async s => await s.WriteAndFlushAsync(obj));
            }
            catch (Exception ex) { }
        }

        private void OnMessageReceive(Message msg) => MessageReceived?.Invoke(this, new MessageEventArgs(msg));

        private void OnMessageSend(Message msg) => MessageSend?.Invoke(this, new MessageEventArgs(msg));

        private void OnMessageGroupSend(Message msg) => MessageGroupSend?.Invoke(this, new MessageEventArgs(msg));

        /// <summary>
        /// 所有连接进来的客户端
        /// </summary>
        private static volatile ConcurrentDictionary<int, IChannel> AllClients = new ConcurrentDictionary<int, IChannel>();

        public override bool IsSharable => true;//标注一个channel handler可以被多个channel安全地共享。

        //  重写基类的方法，当消息到达时触发，这里收到消息后，在控制台输出收到的内容，并原样返回了客户端
        public override async void ChannelRead(IChannelHandlerContext context, object message)
        {
            await Task.Run(() =>
            {
                if (message is Message oo)
                {
                    OnMessageReceive(oo);
                }
            });

            //if (message is Message oo)
            //{
            //    switch (oo.Command)
            //    {
            //        case COMMAND.Message:
            //            Log.Debug($"解码器方式，从客户端接收:{oo.Content}:{DateTime.Now}");
            //            Message ms = new Message { Command = COMMAND.Message, Content = "服务端从客户端接收到内容后返回，我是服务端" };
            //            context.WriteAndFlushAsync(ms);
            //            return;
            //        default:
            //            Log.Debug($"解码器方式，客户端心跳:{oo.Content}");
            //            Message hb = new Message { Command = COMMAND.Message, Content = "服务端接收到心跳连接" };
            //            context.WriteAndFlushAsync(hb);//写入输出流
            //            return;
            //    }
            //}
            //if (message is byte[] o)
            //{
            //    Log.Information($"解码器方式，从客户端接收:{Encoding.UTF8.GetString(o)}:{DateTime.Now}");
            //    //心跳检测
            //    if (Encoding.UTF8.GetString(o).Contains("biubiu:"))
            //    {
            //        //通过编码器,发送至客户端
            //        string temp = "服务端接收到心跳连接";
            //        context.WriteAsync(temp);//写入输出流
            //        return;
            //    }
            //}

            ////通过编码器,发送至客户端
            //string msg = "服务端从客户端接收到内容后返回，我是服务端";
            //context.WriteAsync(msg);//写入输出流

            //if (message is IByteBuffer buffer)
            //{
            //    Log.Debug("从客户端接收: " + buffer.ToString(Encoding.UTF8));
            //}

            ////编码成IByteBuffer,发送至客户端
            //string msg = "服务端从客户端接收到内容后返回，我是服务端";
            //byte[] messageBytes = Encoding.UTF8.GetBytes(msg);
            //IByteBuffer initialMessage = Unpooled.Buffer(messageBytes.Length);
            //initialMessage.WriteBytes(messageBytes);

            //context.WriteAsync(initialMessage);//写入输出流
        }

        private int lossConnectCount = 0;

        //心跳机制
        public override void UserEventTriggered(IChannelHandlerContext context, object evt)
        {
            Log.Debug("已经15秒未收到客户端的消息了！");
            if (evt is IdleStateEvent eventState)
            {
                if (eventState.State == IdleState.ReaderIdle)
                {
                    lossConnectCount++;
                    if (lossConnectCount > 2)
                    {
                        Log.Debug("关闭这个不活跃通道！");
                        context.CloseAsync();
                    }
                }
            }
            else
            {
                base.UserEventTriggered(context, evt);
            };
        }

        // 输出到客户端，也可以在上面的方法中直接调用WriteAndFlushAsync方法直接输出
        public override void ChannelReadComplete(IChannelHandlerContext context) => context.Flush();

        //捕获 异常，并输出到控制台后断开链接，提示：客户端意外断开链接，也会触发
        public override void ExceptionCaught(IChannelHandlerContext context, Exception exception)
        {
            Log.Error(exception, "异常");
            context.CloseAsync();
        }

        private static volatile IChannelGroup groups;

        //客户端连接进来时
        public override async void HandlerAdded(IChannelHandlerContext context)
        {
            await Task.Run(() =>
            {
                base.HandlerAdded(context);
                Log.Debug($"客户端{context}上线.");
                //客户端首次连接成功发送信息到
                Message ms = new Message { Command = COMMAND.ServerToClient, Eoperation=Operation.UserLogin};
                AllClients.AddOrUpdate((context.Channel.RemoteAddress as IPEndPoint).Port, context.Channel, (k, v) => v);
                OnMessageGroupSend(ms);
            });
        }

        //客户端下线断线时
        public override async void HandlerRemoved(IChannelHandlerContext context)
        {
            await Task.Run(() =>
            {
                Log.Debug($"客户端{context}下线.");
                base.HandlerRemoved(context);

                AllClients.TryRemove((context.Channel.RemoteAddress as IPEndPoint).Port, out IChannel temp);

                Message ms = new Message { Command = COMMAND.Message, Content = $"恭送{context.Channel.RemoteAddress}离开." };
                OnMessageGroupSend(ms);
            });
        }

        //服务器监听到客户端活动时
        public override async void ChannelActive(IChannelHandlerContext context)
        {
            _Socket = context;//赋值
            await Task.Run(() =>
            {
                Log.Debug($"客户端{context.Channel.RemoteAddress}在线.");
                base.ChannelActive(context);
            });
        }

        //服务器监听到客户端不活动时
        public override void ChannelInactive(IChannelHandlerContext context)
        {
            Log.Debug($"客户端{context.Channel.RemoteAddress}离线了.");
            base.ChannelInactive(context);
        }
    }
}